/*
  RadioGroup: alternative to RadioButtonContainer.

  Jason Hood, 10 to 14 December, 2000.

  This class is virtually identical to RadioButtonContainer.
  The differences are:
    * an event is generated when a button is (re)selected;
    * an extra line between the frame and first item;
    * up and down will wrap.
*/

#include "radiogrp.h"


DEFINE_RESPONSE_TABLE(RadioGroup, Window)
  if (isFocus() && n)
  {
    E_KEYCODE(0xE0, 0x48, KeyUp)	// Grey Up
    E_KEYCODE(0x00, 0x48, KeyUp)	// KP 8
    E_KEYCODE(0xE0, 0x50, KeyDown)	// Grey Down
    E_KEYCODE(0x00, 0x50, KeyDown)	// KP 2
    E_KEYCODE(0x0D, 0x1C, KeyEnter)	// Enter
    E_KEYCODE(0x20, 0x39, KeyEnter)	// Space
    E_KEYCODE(0x0D, 0xE0, KeyEnter)	// KP Enter
  }

  if (ev->Type == W_NOTIFY)
  {
    for (int j = 0; j < n; ++j)
    {
      if (ev->p1 != button[j]->GetControlID()) button[j]->DeSelect();
      else
      {
	pos = j;
	ws.QueueEvent(parent, event(W_NOTIFY, button[j]->GetControlID(), 2002));
      }
    }
    return true;
  }
END_RESPONSE_TABLE


RadioGroup::RadioGroup(Window *parent, int x1, int y1, int x2, int y2, int t)
  : Window(parent, NULL, x1, y1, x2, y2,
	   WA_CLIENT|WA_DEPENDANT|WA_TABSTOP|WA_VISABLE),
    n(0), pos(0), type(t), buttons(5)
{
  button = new RadioButton*[buttons];
}


RadioGroup::~RadioGroup()
{
  while (n > 0) delete button[--n];
  delete button;
}


void RadioGroup::AddButton(char* text, ControlID ID)
{
  if (n == buttons)
  {
    RadioButton** temp = button;
    button = new RadioButton*[buttons+5];
    memcpy(button, temp, buttons * sizeof(RadioButton*));
    delete temp;
    buttons += 5;
  }
  button[n] = new RadioButton(this, 3+n*(SysFont->height+1), w-7, ID, text);
  ++n;
}


void RadioGroup::PaintWindow(int x1, int y1, int x2, int y2)
{
  if (type != RADIO_TYPE_NONE)
  {
    ViewBuffer* buf = GetSubBuffer(x1, y1, x2, y2);

    if (type == RADIO_TYPE_LOWERED || type == RADIO_TYPE_DIP)
    {
      InvFrame(buf, 0, 0, w-1, h-1);
      if (type == RADIO_TYPE_DIP)
	Frame(buf, 1, 1, w-2, h-2);
    }
    else // if (type == RADIO_TYPE_RAISED || type == RADIO_TYPE_BUMP)
    {
      Frame(buf, 0, 0, w-1, h-1);
      if (type == RADIO_TYPE_BUMP)
	InvFrame(buf, 1, 1, w-2, h-2);
    }

    DeleteBuffer(buf);
  }
}


void RadioGroup::Focus()
{
  SetFocus(button[pos]);
}


void RadioGroup::UnFocus()
{
  SetFocus(NULL);
}


void RadioGroup::SelectButton(ControlID ID)
{
  int j;

  for (j = 0; j < n; ++j)
  {
    if (button[j]->GetControlID() == ID)
    {
      if (isFocus())
	button[j]->Select();
      else
	button[j]->SelectWithoutFocus();
      pos = j;
      break;
    }
  }
}


ControlID RadioGroup::GetSelectedButton()
{
  return (n && button[pos]->IsSelected()) ? button[pos]->GetControlID() : -1;
}


void RadioGroup::KeyUp(int)
{
  if (--pos < 0) pos = n - 1;
  button[pos]->Select();
}


void RadioGroup::KeyDown(int)
{
  if (++pos >= n) pos = 0;
  button[pos]->Select();
}


void RadioGroup::KeyEnter(int)
{
  if (button[pos]->IsSelected())
    ws.QueueEvent(parent, event(W_NOTIFY, button[pos]->GetControlID(), 2002));
  else
    button[pos]->Select();
}
